package twoD.Csg;

public class CsgNode {

	private static final int DEFAULT_SAMPLING_RATE = 6;

	public enum Operation {
		UNION, INTERSECTION, DIFFERENCE
	}

	private CsgNode parent;
	private CsgNode left;
	private CsgNode right;

	private IPrimitive primitive;
	private Operation op;

	private int Sampling;

	public CsgNode() {
		parent = null;
		left = null;
		right = null;
		primitive = null;
		op = null;
		Sampling = DEFAULT_SAMPLING_RATE;
	}

	public boolean isPrimitive() {
		return primitive == null ? false : true;
	}

	public void setPrimitive(IPrimitive p) {
		primitive = p;
	}

	public void setSamplingRate(int n) {
		Sampling = n;
	}

	public void setOperation(Operation op, CsgNode A, CsgNode B) {
		this.op = op;
		left = A;
		right = B;
		left.parent = this;
		right.parent = this;
	}

	public CsgNode getParent() {
		return parent;
	}

	public CsgNode getLeft() {
		return left;
	}

	public CsgNode getRight() {
		return right;
	}

	public boolean contain(double... p) {
		if (isPrimitive()) {
			return primitive.contain(p);
		} else {
			if (op == Operation.UNION)
				// return left.contain(p) || right.contain(p);
				/*
				 * optimized operation
				 */
				if (left.contain(p))
					return true;
				else if (right.contain(p))
					return true;
				else
					return false;
			else if (op == Operation.INTERSECTION)
				// return left.contain(p) && right.contain(p);
				/*
				 * optimized operation
				 */
				if (!left.contain(p))
					return false;
				else if (!right.contain(p))
					return false;
				else
					return true;
			else if (op == Operation.DIFFERENCE)
				// return left.contain(p) && !right.contain(p);
				/*
				 * optimized operation
				 */
				if (!left.contain(p))
					return false;
				else if (right.contain(p))
					return false;
				else
					return true;
			else
				return false;
		}
	}

	public boolean isUniform(double x, double y, double size) {
		double d = size / Sampling;
		boolean m = contain(x + size / 2, y + size / 2);

		for (int i = 0; i <= Sampling; i++) {
			double px = x + i * d;
			for (int j = 0; j <= Sampling; j++) {
				double py = y + j * d;
				if (m != contain(px, py)) {
					return false;
				}
			}
		}
		return true;
	}

	public boolean isUniform(double x, double y, double z, double size) {
		double d = size / Sampling;
		boolean m = contain(x + size / 2, y + size / 2, z + size / 2);

		for (int i = 0; i <= Sampling; i++) {
			double px = x + i * d;
			for (int j = 0; j <= Sampling; j++) {
				double py = y + j * d;
				for (int k = 0; k <= Sampling; k++) {
					double pz = z + k * d;
					if (m != contain(px, py, pz)) {
						return false;
					}
				}
			}
		}
		return true;
	}

}
